package com.soriya.nestlive.screen.live

import android.annotation.SuppressLint
import android.app.Activity
import android.graphics.Rect
import android.util.Log
import android.view.ViewGroup
import android.view.ViewTreeObserver
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.MaterialTheme
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Face4
import androidx.compose.material.icons.filled.Send
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.view.WindowCompat
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.ksyun.media.player.KSYMediaPlayer
import com.ksyun.media.player.KSYTextureView
import com.shuyu.gsyvideoplayer.builder.GSYVideoOptionBuilder
import com.shuyu.gsyvideoplayer.utils.GSYVideoType
import com.soriya.nestlive.component.CustomEditText
import com.soriya.nestlive.component.CustomImage
import com.soriya.nestlive.component.GsyPlayer
import com.soriya.nestlive.component.LiveChatArea
import com.soriya.nestlive.component.LiveTitle
import com.soriya.nestlive.component.ScreenColumnContent
import com.soriya.nestlive.component.ScreenConstraintContent
import com.soriya.nestlive.component.SmallText
import com.soriya.nestlive.component.SmallerAdditionalText
import com.soriya.nestlive.component.Streamer
import com.soriya.nestlive.constant.ServerConstant
import com.soriya.nestlive.constant.UIValue
import com.soriya.nestlive.model.Channel
import com.soriya.nestlive.model.Live
import com.soriya.nestlive.model.LiveChat
import com.soriya.nestlive.util.WindowUtil
import com.soriya.nestlive.viewmodel.ChannelModel
import com.soriya.nestlive.viewmodel.LiveChatModel
import com.soriya.nestlive.viewmodel.LiveModel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

@Composable
fun LiveDetailScreen(
    channelId: Long = 0,
    toBack: () -> Unit
) {
    val channelModel: ChannelModel = hiltViewModel()
    val liveModel: LiveModel = hiltViewModel()

//    val channel by channelModel.channelDetail.collectAsState()
//    channelModel.getDetailById(channelId)

    val live by liveModel.liveDetail.collectAsState()

    LaunchedEffect(Unit) {
        liveModel.getLiveByChannelId(channelId)
    }

    if (live != null) {
        if (live!!.orientation == 0) HorizontalLive(
            channelId = channelId,
            live = live!!,
            toBack = toBack
        ) else VerticalLive(
            channelId = channelId,
            live = live!!,
            toBack = toBack
        )
    }
}

@Composable
private fun HorizontalLive(
    channelId: Long,
    live: Live,
    toBack: () -> Unit
) {
    val context = LocalContext.current as Activity

    val bottomPadding = remember {
        mutableStateOf(0)
    }

    val chatModel: LiveChatModel = hiltViewModel()

    Column {

        val widthDp = WindowUtil.getScreenWidthToDp(context)

        val url = ServerConstant.RTMP_URL + channelId

        val optionBuilder = GSYVideoOptionBuilder()
            .setCacheWithPlay(true)
            .setVideoTitle(live.liveName)
            .setIsTouchWiget(true)
            //.setAutoFullWithSize(true)
            .setRotateViewAuto(false)
            .setLockLand(false)
            .setShowFullAnimation(false) // 打开动画
            .setNeedLockFull(true)
            .setSeekRatio(1F)
        GsyPlayer(
            url = url,
            optionBuilder = optionBuilder,
            modifier = Modifier
                .fillMaxWidth()
                .height((widthDp * 9 / 16).dp) // 16 : 9
        )

        ScreenColumnContent(
            modifier = Modifier.padding(bottom = bottomPadding.value.dp)
        ) {
            Streamer(data = live)
            BulletScreen(channelId = channelId, modifier = Modifier.weight(1F))
            CommentEditText(onSend = {
                chatModel.sendLiveComment(channelId, it)
            })
        }
    }
}

@SuppressLint("InternalInsetResource", "DiscouragedApi")
@Composable
private fun VerticalLive(
    channelId: Long,
    live: Live,
    toBack: () -> Unit
) {
    val context = LocalContext.current as Activity
    val uiController = rememberSystemUiController()

    var keyHeight by remember {
        mutableStateOf(0)
    }

    val rootView = context.window.decorView.rootView
    val resources = context.resources
    val sId = resources.getIdentifier("status_bar_height", "dimen", "android")
    val nId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
    val statusBarHeight = resources.getDimensionPixelSize(sId)
    val navigationBarHeight = resources.getDimensionPixelSize(nId)
    val listener: ViewTreeObserver.OnGlobalLayoutListener = ViewTreeObserver.OnGlobalLayoutListener {
        val rect = Rect()
        context.window.decorView.rootView.getWindowVisibleDisplayFrame(rect)

        keyHeight = context.window.decorView.height - ((rect.bottom - rect.top) + navigationBarHeight + statusBarHeight)
    }
    rootView.viewTreeObserver.addOnGlobalLayoutListener(listener)

    val lifecycle = LocalLifecycleOwner.current.lifecycle

    DisposableEffect(Unit) {

        val lifecycleEventObserver = LifecycleEventObserver { _, event ->
            when (event) {
                Lifecycle.Event.ON_CREATE -> {}
                Lifecycle.Event.ON_RESUME -> {}
                Lifecycle.Event.ON_PAUSE -> {}
                Lifecycle.Event.ON_DESTROY -> {
                    rootView.viewTreeObserver.removeOnGlobalLayoutListener(listener)
                }
                else -> {}
            }
        }

        lifecycle.addObserver(lifecycleEventObserver)

        onDispose {
            lifecycle.removeObserver(lifecycleEventObserver)
        }
    }

    val color = MaterialTheme.colors.primary

    uiController.setSystemBarsColor(Color.Transparent, darkIcons = true)
    WindowCompat.setDecorFitsSystemWindows(context.window, false)

    val chatModel: LiveChatModel = hiltViewModel()

    Box(
        modifier = Modifier
            .background(Color.Black.copy(0.8F))
            .navigationBarsPadding()
    ) {
        val url = ServerConstant.RTMP_URL + channelId

        GSYVideoType.setShowType(GSYVideoType.SCREEN_TYPE_FULL)
        val optionBuilder = GSYVideoOptionBuilder()
            .setCacheWithPlay(true)
            .setVideoTitle(live.liveName)
            .setIsTouchWiget(false)
            .setRotateViewAuto(false)
            .setLockLand(false)
            .setShowFullAnimation(false) // 打开动画
            .setNeedLockFull(true)
            .setSeekRatio(1F)
            .setDismissControlTime(0)

        GsyPlayer(url = url, optionBuilder = optionBuilder, modifier = Modifier.fillMaxSize())

        ScreenColumnContent(
            modifier = Modifier.padding(bottom = WindowUtil.pxToDp(context, keyHeight).dp)
        ) {
            LiveTitle(
                modifier = Modifier
                    .statusBarsPadding()
                    .padding(top = 20.dp)
            ) {
                toBack()
            }

            Column(
                verticalArrangement = Arrangement.Bottom,
                modifier = Modifier.weight(1F)
            ) {
                LiveChatArea(
                    channelId = channelId,
                    modifier = Modifier
                )
            }

            CommentEditText(
                onSend = {
                    chatModel.sendLiveComment(channelId, it)
                },
                modifier = Modifier
                    .padding(bottom = 10.dp)
            )
        }
        if (false) ScreenConstraintContent(
            modifier = Modifier.padding(bottom = WindowUtil.pxToDp(context, keyHeight).dp)
        ) {
            val (title, input, chat) = createRefs()

            LiveTitle(
                modifier = Modifier
                    .statusBarsPadding()
                    .constrainAs(title) {
                        top.linkTo(parent.top, margin = 20.dp)
                        start.linkTo(parent.start)
                        end.linkTo(parent.end)
                    }
            ) {
                toBack()
            }

            CommentEditText(
                onSend = {
                    chatModel.sendLiveComment(channelId, it)
                },
                modifier = Modifier
                    .constrainAs(input) {
                        bottom.linkTo(parent.bottom, margin = 10.dp)
                        start.linkTo(parent.start)
                        end.linkTo(parent.end)
                    }
            )

            LiveChatArea(
                channelId = channelId,
                modifier = Modifier
                    .constrainAs(chat) {
                        bottom.linkTo(input.top, margin = 10.dp)
                        start.linkTo(parent.start)
                    }
            )
        }
    }

    DisposableEffect(Unit) {
        onDispose {
            uiController.setSystemBarsColor(color)
            WindowCompat.setDecorFitsSystemWindows(context.window, true)
        }
    }
}

@Composable
private fun KSYPlayer(channelId: Long, onVideoPlay: () -> Unit) {
    var ksyTextureView: KSYTextureView? = null

    AndroidView(
        factory = { context ->

            val TAG = "SoRiya"

            ksyTextureView = KSYTextureView(context)

            val mTextureView: KSYTextureView = ksyTextureView!!

            mTextureView.layoutParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
            )

            val dataSource = ServerConstant.RTMP_URL + channelId

            mTextureView.dataSource = dataSource

            mTextureView.setVideoScalingMode(KSYMediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING)

            mTextureView.setDecodeMode(KSYMediaPlayer.KSYDecodeMode.KSY_DECODE_MODE_AUTO)

            mTextureView.setOnPreparedListener {
                Log.i(TAG, "setOnPreparedListener")
            }

            mTextureView.setOnErrorListener { iMediaPlayer, i, i2 ->
                Log.i(TAG, "Error: v: $iMediaPlayer, i1: $i, i2: $i2")
                return@setOnErrorListener true
            }

            mTextureView.setOnInfoListener { v, i, i2 ->
                Log.i(TAG, "v: $v, i1: $i, i2: $i2")

                when (i) {
                    KSYMediaPlayer.MEDIA_INFO_BUFFERING_START -> {
                        Log.i(TAG, "开始缓冲数据")
                    }
                    KSYMediaPlayer.MEDIA_INFO_AUDIO_RENDERING_START -> {
                        Log.i(TAG, "开始播放音频")
                    }
                    KSYMediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START -> {
                        Log.i(TAG, "开始渲染视频")
                        onVideoPlay()
                    }
                    KSYMediaPlayer.MEDIA_INFO_SUGGEST_RELOAD -> {
                        mTextureView.reload(dataSource, false, KSYMediaPlayer.KSYReloadMode.KSY_RELOAD_MODE_ACCURATE)
                    }
                    KSYMediaPlayer.MEDIA_INFO_RELOADED -> {
                        Log.i(TAG, "Reload成功")
                    }
                }

                return@setOnInfoListener false
            }

            mTextureView.shouldAutoPlay(true) // 自动开播
            mTextureView.prepareAsync()

            mTextureView
        },
        modifier = Modifier.fillMaxSize()
    )

    val lifecycle = LocalLifecycleOwner.current.lifecycle

    DisposableEffect(Unit) {

        val lifecycleEventObserver = LifecycleEventObserver { _, event ->
            when (event) {
                Lifecycle.Event.ON_RESUME -> {
                    ksyTextureView?.runInForeground()
                }
                Lifecycle.Event.ON_PAUSE -> {
                    ksyTextureView?.runInBackground(false) // true后台音频继续播放 false停止所有播放
                }
                else -> {}
            }
        }

        lifecycle.addObserver(lifecycleEventObserver)

        onDispose {
            ksyTextureView?.release()
            lifecycle.removeObserver(lifecycleEventObserver)
        }
    }
}

@Composable
private fun BulletScreen(channelId: Long, modifier: Modifier = Modifier) {

    val listState = rememberLazyListState()

    val liveChatModel: LiveChatModel = hiltViewModel()
    val liveChatState = remember {
        mutableStateListOf<LiveChat>()
    }
    val chatChannel = remember {
        liveChatModel.liveChat(channelId)
    }

    LaunchedEffect(listState) {
        for (it in chatChannel) {
            liveChatState.add(it)
            listState.animateScrollToItem(liveChatState.size)
        }
    }

    DisposableEffect(Unit) {
        onDispose {
            liveChatModel.closeChannel()
        }
    }

    LazyColumn(
        state = listState,
        modifier = modifier
    ) {
        items(liveChatState.size) { index ->
            val liveChat = liveChatState[index]
            BulletScreenItem(liveChat)
        }
    }
}

@Composable
private fun BulletScreenItem(liveChat: LiveChat) = Row(
    verticalAlignment = Alignment.CenterVertically
) {
    CustomImage(
        url = "https://img0.baidu.com/it/u=1149380132,3232861229&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500",
        contentDescription = "Avatar",
        shape = CircleShape,
        modifier = Modifier.size(40.dp)
    )

    Spacer(modifier = Modifier.width(10.dp))

    Column(
        verticalArrangement = Arrangement.SpaceBetween,
        modifier = Modifier.padding(vertical = UIValue.VERTICAL_PADDING)
    ) {
        SmallerAdditionalText(text = liveChat.nickname)
        SmallText(text = liveChat.content)
    }
}

@Composable
private fun CommentEditText(
    modifier: Modifier = Modifier,
    onSend: (String) -> Unit
) {
    var commentContent by remember {
        mutableStateOf("")
    }

    CustomEditText(
        value = commentContent,
        onValueChange = {
            commentContent = it
        },
        leftIcon = Icons.Default.Face4,
        rightIcon = Icons.Default.Send,
        rightIconOnClick = {
            onSend(commentContent)
        },
        modifier = modifier
            .fillMaxWidth()
            .padding(vertical = UIValue.VERTICAL_PADDING)
    )
}